//
//  YuanXinPhotoLibraryImageLoader.m
//  YuanXinCamera
//
//  Created by 晏德智 on 16/10/11.
//  Copyright © 2016年 晏德智. All rights reserved.
//

#import "YuanXinPhotoLibraryImageLoader.h"
#import <Photos/Photos.h>

#define iOS8Later ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)

/**
 * 只要不是重定义为其它类型，可以重定义。
 * 重定义 RCTImageLoaderPartialLoadBlock
 * rn 在 0.38.1 上定义了该类型，RCTImageURLLoader 协议方法也相应变了，
 * 所以在低于此版本的 rn 上找不到这个类型，这里重定义一下保证可以找到
 * 。。不得已出此下策，若以后 rn 有新版本改变该类型则需要和 rn 版本同步再兼容
 */
//typedef void (^RCTImageLoaderPartialLoadBlock)(UIImage *image);

@implementation YuanXinPhotoLibraryImageLoader

RCT_EXPORT_MODULE()

@synthesize bridge = _bridge;

- (BOOL)canLoadImageURL:(NSURL *)requestURL
{
    return [requestURL.scheme caseInsensitiveCompare:@"yuanxin-assets"] == NSOrderedSame || [requestURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame;
}

- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
                                              size:(CGSize)size
                                             scale:(CGFloat)scale
                                        resizeMode:(RCTResizeMode)resizeMode
                                   progressHandler:(RCTImageLoaderProgressBlock)progressHandler
                                 completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
{
    return [self loadImageForURL:imageURL size:size scale:scale resizeMode:resizeMode progressHandler:progressHandler partialLoadHandler:nil completionHandler:completionHandler];
}

- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
                                              size:(CGSize)size
                                             scale:(CGFloat)scale
                                        resizeMode:(RCTResizeMode)resizeMode
                                   progressHandler:(RCTImageLoaderProgressBlock)progressHandler
                                partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
                                 completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
{
    
    NSString *assetID = @"";
    PHFetchResult *results;
    if ([imageURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
        assetID = [imageURL.absoluteString substringFromIndex:@"assets-library://".length];
        results = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil];
    } else if ([imageURL.scheme caseInsensitiveCompare:@"yuanxin-assets"] == NSOrderedSame) {
        assetID = [imageURL.absoluteString substringFromIndex:@"yuanxin-assets://".length];
        results = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
    } else {
        assetID = [imageURL.absoluteString substringFromIndex:@"ph://".length];
        results = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
    }
    if (results.count == 0) {
        NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", assetID];
        completionHandler(RCTErrorWithMessage(errorText), nil);
        return ^{};
    }
    
    PHAsset *asset = [results firstObject];
    PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
    
    // Allow PhotoKit to fetch images from iCloud
    imageOptions.networkAccessAllowed = YES;
    
    if (progressHandler) {
        imageOptions.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary<NSString *, id> *info) {
            static const double multiplier = 1e6;
            progressHandler(progress * multiplier, multiplier);
        };
    }
    
    // Note: PhotoKit defaults to a deliveryMode of PHImageRequestOptionsDeliveryModeOpportunistic
    // which means it may call back multiple times - we probably don't want that
    imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
    
    BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
    CGSize targetSize;
    if (useMaximumSize) {
        targetSize = PHImageManagerMaximumSize;
        imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
    } else {
        targetSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
        imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
    }
    
    PHImageContentMode contentMode = PHImageContentModeAspectFill;
    if (resizeMode == RCTResizeModeContain) {
        contentMode = PHImageContentModeAspectFit;
    }
    
    /* 需要完整的图片信息，所以换用下面的 requestImageDataForAsset，再转为图片以保持图片方向信息等
    PHImageRequestID requestID =
    [[PHImageManager defaultManager] requestImageForAsset:asset
                                               targetSize:targetSize
                                              contentMode:contentMode
                                                  options:imageOptions
                                            resultHandler:^(UIImage *result, NSDictionary<NSString *, id> *info) {
                                                if (result) {
                                                    completionHandler(nil, result);
                                                } else {
                                                    completionHandler(info[PHImageErrorKey], nil);
                                                }
                                            }];
    */
    PHImageRequestID requestID =
    [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
        // 直接得到最终的 NSData 数据
        if (imageData) {
            UIImage *result = [UIImage imageWithData:imageData];
            completionHandler(nil, result);
        } else {
            completionHandler(info[PHImageErrorKey], nil);
        }
    }];
    
    return ^{
        [[PHImageManager defaultManager] cancelImageRequest:requestID];
    };
    
}

@end

